/**
 * 
 */
package email.core;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TableItem;

import email.Main;
import email.core.EmailChecker.MessageListCallback;

public class EmailPoller {
	final transient Logger LOGGER = Logger.getLogger(this.getClass().getName());
	EmailChecker checker;
	MessageListUpdater messageListUpdater;
	TableItem item;
	int poll;
	
	Thread pollingThread;
	
	public EmailPoller(EmailChecker checker, MessageListUpdater messageListUpdater, final TableItem item, int poll, Shell shell) {
		this.checker = checker;
		this.messageListUpdater = messageListUpdater;
		this.item = item;
		this.checker.setCallback(this.getMessageListCallback(shell));
		this.poll = poll;
	}
	
	MessageListCallback getMessageListCallback(final Shell shell) {
		return new MessageListCallback() {
			@Override
			public void onError(final String errorMessage) {
				setMailboxItemColumnText(shell,Main.STATUS_COLUMN_INDEX, errorMessage);
				startPolling(shell);
			}

			@Override
			public void onMessageList(List<EmailMessage> messages) {
				setMailboxItemColumnText(shell,Main.STATUS_COLUMN_INDEX, ConfigurationProvider.getInstance().getMessageString("check.status.checked"));
				setMailboxItemColumnText(shell,Main.MESSAGE_COUNT_COLUMN_INDEX, ""+messages.size());
				if (messageListUpdater!=null) {
					messageListUpdater.onMessageList(item, messages);
				}
				startPolling(shell);
			}

			@Override
			public void onStatusChange(final String statusMessage) {
				setMailboxItemColumnText(shell,Main.STATUS_COLUMN_INDEX, statusMessage);
			}
		};
	}

	void setMailboxItemColumnText(Shell shell, final int columnIndex, final String text) {
		shell.getDisplay().asyncExec(new Runnable(){
			@Override
			public void run() {
				item.setText(columnIndex, text);
			}});
	}
	
	public synchronized void startPolling(final Shell shell) {
		if (this.pollingThread!=null) { this.pollingThread.interrupt(); }
		pollingThread = new Thread() {
			void checkInterrupted() throws InterruptedException {
				Thread.yield();
				if (this.isInterrupted()) { throw new InterruptedException("Interrupted"); }
			}
			@Override
			public void run() {
				try {
					for (int i=poll; i>0; i--) {
							this.checkInterrupted();
							setMailboxItemColumnText(shell, Main.POLL_COLUMN_INDEX, i+" "+ConfigurationProvider.getInstance().getMessageString("mailbox.table.column.poll.min"));
							Thread.sleep(60*1000);
							
					}
					this.checkInterrupted();
					setMailboxItemColumnText(shell, Main.POLL_COLUMN_INDEX, "0 "+ConfigurationProvider.getInstance().getMessageString("mailbox.table.column.poll.min"));
					this.checkInterrupted();
					checkMessages(shell, null, null);
				} catch (InterruptedException e) {
					LOGGER.log(Level.INFO, "Poller thread interrupted. Stop polling");
				}
			}
		};
		pollingThread.start();
	}
	
	synchronized void checkMessages(Shell shell, List<String> deleteIds, List<String> loadIds){
		this.setMailboxItemColumnText(shell, Main.STATUS_COLUMN_INDEX, ConfigurationProvider.getInstance().getMessageString("check.status.checking"));
		checker.loadMessagesList(deleteIds, loadIds);
	}
	
	/**
	 * Forces the poller to check messages
	 */
	public synchronized void checkNow(Shell shell) {
		if (pollingThread!=null) {pollingThread.interrupt();}
		this.checkMessages(shell, null, null);
	}

	/**
	 * Forces the poller to stop checking messages
	 */
	public synchronized void stopChecker() {
		checker.stopCheckThread();
	}
	
	/**
	 * Forces the checker to check messages along with deleting specified ones
	 * @param messageIds
	 */
	public synchronized void deleteMessages(Shell shell, List<String> messageIds) {
		if (pollingThread!=null) { pollingThread.interrupt(); }
		this.checkMessages(shell, messageIds, null);
	}

	/**
	 * Forces the checker to check messages along with fetching specified ones
	 * @param messageIds
	 */
	public synchronized void loadMessages(List<String> messageIds) {
	}
	
	public synchronized void stopPolling() {
		this.stopChecker();
		if (pollingThread!=null) {pollingThread.interrupt();}
	}
}